/**
 * DSM - Distributed Search Manager
 * Developed by Milspec Research International Pty Ltd
 * $Author: vhobbs $
 * $Revision: 1.6 $
 * $Date: 2007/01/03 23:07:46 $
 * (c)Copyright 2004
 * education.au limited
 * DEST
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * Neither the names education.au limited, DEST nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 * To the extent permitted by law, the copyright owners of this software and
 * its contributors:
 * (i) exclude all warranties in relation to the software; and
 * (ii) exclude liability for all losses, costs, expenses and damages arising
 * in any way from the use of the software whether arising from or in
 * relation to breach of contract, negligence or any other tort, in equity
 * or otherwise. If the software is in breach of a warranty which is
 * implied by law, the copyright owners and contributors liability is
 * limited to the replacement of the software.
 *
 * @author	gsingh
 */

package au.edu.educationau.opensource.dsm.adapters.contenthandler;

import java.util.ArrayList;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import au.edu.educationau.opensource.dsm.adapters.SearchAdapterProperties;
import au.edu.educationau.opensource.dsm.obj.SearchCriteria;
import au.edu.educationau.opensource.dsm.obj.SearchResult;
import au.edu.educationau.opensource.dsm.worker.ResultSetUnifier;

public class LOMXMLContentHandler extends DefaultHandler {
	private SearchResult result = new SearchResult();
	private ArrayList results = new ArrayList();
	private ArrayList metadata = new ArrayList(1);

	private String currentElement = "";
	private boolean isGeneral = false;
	private boolean isTitle = false;
	private boolean isDescription = false;
	private boolean isLifecycle = false;
	private boolean isTechnical = false;
	private SearchAdapterProperties props = new SearchAdapterProperties();
	private SearchCriteria criteria = null;

	/***/
	public ArrayList getResults() {
		// LOM provides no relevance, so use rank to spread relevance scores
		// over a Normal distribution
		// TODO: test an adapter-specific property to see if we should resort
		// prior
		// to converting rank to relevance
		ResultSetUnifier.normalizeResultsToZipfianDistribution(results, criteria);
		return results;
	}

	/**
	 * @param props
	 */
	public void setSearchAdapterProperties(SearchAdapterProperties props) {
		this.props = props;
	}

	/**
	 * @param criteria
	 */
	public void setSearchCriteria(SearchCriteria criteria) {
		this.criteria = criteria;
	}

	/**
	 * @param ch
	 * @param ch_start
	 * @param ch_length
	 * @exception SAXException
	 */
	public void characters(char[] ch, int ch_start, int ch_length) throws SAXException {
		String val = String.copyValueOf(ch, ch_start, ch_length);

		if (isGeneral) {
			if (currentElement.equals("entry")) {
				// Priority for this link
				result.setLink(props.getExtraProperty("identifier.prefix") + val);
			}

			if (isTitle && currentElement.equals("string")) {
				result.setTitle(val);
			}

			if (isDescription && currentElement.equals("string")) {
				result.setDescription(val);
			}
		}

		if (isLifecycle) {
			if (currentElement.equals("datetime")) {
				result.setDate(val);
			}
		}

		if (isTechnical) {
			// Secondary link
			if (currentElement.equals("location")) {
				result.setLink(val);
			}
		}

		currentElement = "";
		// QueryResult
	}

	/**
	 * @param ch
	 * @param ch_start
	 * @param ch_length
	 * @exception SAXException
	 */
	public void ignorableWhitespace(char[] ch, int ch_start, int ch_length) throws SAXException {
	}

	/**
	 * @param uri
	 * @param localName
	 * @param qName
	 * @exception SAXException
	 */
	public void endElement(java.lang.String uri, java.lang.String localName, java.lang.String qName) throws SAXException {
		String element = localName.toLowerCase();

		if (localName.equals("lom")) {
			/*
			 * result.setRelevance( ResultSetUnifier.normaliseRelevance(0f,
			 * props.getRelevanceMultiplier(), props.getRelevanceOffset()));
			 */
			float combinedHitFrequency = ResultSetUnifier.getHitFrequency(criteria.getQueryArray(), result.getTitle(), result.getDescription(), criteria.getKeywordConstraint(), criteria.isCaseSensitive());
			// result.setHitFrequency(combinedHitFrequency);
			result.setSource(props.getAdapterCode());
			result.setCollectionName(props.getDisplayTitle());
			results.add(result);
		}
		if (element.equals("general")) {
			isGeneral = false;
		} else if (element.equals("lifecycle")) {
			isLifecycle = false;
		} else if (element.equals("title")) {
			isTitle = false;
		} else if (element.equals("description")) {
			isDescription = false;
		} else if (element.equals("technical")) {
			isTechnical = false;
		}
	}

	/**
	 * @param target
	 * @param data
	 * @exception SAXException
	 */
	public void processingInstruction(String target, String data) throws SAXException {
	}

	/**
	 * @param uri
	 * @param localName
	 * @param qName
	 * @param attr
	 * @exception SAXException
	 */
	public void startElement(java.lang.String uri, java.lang.String localName, java.lang.String qName, Attributes attr) throws SAXException {
		this.currentElement = localName.toLowerCase();

		if (currentElement.equals("lom")) {
			result = new SearchResult();
			metadata = new ArrayList(1);
		}

		if (currentElement.equals("general")) {
			isGeneral = true;
		} else if (currentElement.equals("lifecycle")) {
			isLifecycle = true;
		} else if (currentElement.equals("title")) {
			isTitle = true;
		} else if (currentElement.equals("description")) {
			isDescription = true;
		} else if (currentElement.equals("technical")) {
			isTechnical = true;
		}
	}

} // class LOMXMLContentHandler

// --EOF
